package com.cc.data_explore.logic.mybatis;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.cc.data_explore.logic.mybatis.mapper.sub.TableConfigMapper;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Getter;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import javax.sql.DataSource;

/**
 * @author cc
 * @version 1.0
 * @since 2025/3/29
 */

public class Db {

    @Getter
    private SqlSessionFactory sqlSessionFactory;
    private DataSource dataSource;

    private Db() {
    }

    public Db(String dbName, String mapperPath) {
        this.dataSource = dataSource(dbName);
        sqlSessionFactory = initSqlSessionFactory(dbName, mapperPath);
        if (!DbHelper.MAIN_DB_NAME.equals(dbName)) {
            try (SqlSession session = sqlSessionFactory.openSession()) {
                session.getMapper(TableConfigMapper.class).initBaseTable();
            }
        }
        DbHelper.getInstance().putDb(dbName, this);
    }

    private SqlSessionFactory initSqlSessionFactory(String dbName, String mapperPath) {
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment(dbName, transactionFactory, dataSource);
        MybatisConfiguration configuration = new MybatisConfiguration(environment);
        configuration.addMappers(mapperPath);
        //configuration.setLogImpl(StdOutImpl.class);
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.DUCKDB));
        configuration.addInterceptor(interceptor);
        String resource = "/mappers/TableConfigMapper.xml";
        String resource1 = "/mappers/AnalysisTableMapper.xml";
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(this.getClass().getResourceAsStream("/mappers/TableConfigMapper.xml"), configuration, resource, configuration.getSqlFragments());
        xmlMapperBuilder.parse();
        XMLMapperBuilder xmlMapperBuilder1 = new XMLMapperBuilder(this.getClass()
                                                                      .getResourceAsStream("/mappers/AnalysisTableMapper.xml"), configuration, resource1, configuration.getSqlFragments());
        xmlMapperBuilder1.parse();
        return new MybatisSqlSessionFactoryBuilder().build(configuration);
    }

    private DataSource dataSource(String dbName) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName("org.duckdb.DuckDBDriver");
        hikariConfig.setJdbcUrl("jdbc:duckdb:" + dbName);
        return new HikariDataSource(hikariConfig);
    }

    public void close() {
        HikariDataSource hikariDataSource = (HikariDataSource) this.dataSource;
        hikariDataSource.close();
    }
}
